///******************** NG.Respate(C)  **********************************
//* 产品名称: Respate 科技
//* 文件名称: signal.c
//* 程序作者: 雷帕特公司(南宫子萍)
//* 程序版本: V1.1														   
//* 编制日期: 2019/1/29
//* 功能描述: 系统日志
//* QQ:	2085827949
//**********************************************************************/

#include <unistd.h>
#include "stdio.h"
#include "stdlib.h"
#include "lap_lib.h"
// #include "laperro.h"

#if 0

// 闹钟 定时
#include <unistd.h>
#include <signal.h>
// unsigned int alarm(unsigned int seconds);

static void Lap_alarm()
{
  sigset_t set;
  unsigned int sl = 1; // 睡眠时间
  unsigned int r_sl = 0;

  sigemptyset(&set);
  sigaddset(&set,SIGALRM);          // 添加信号
  sigprocmask(SIG_BLOCK,&set,NULL); // 阻塞信号

  while(1)
  {
    siginfo_t info;

    r_sl = alarm(sl);
    printf("new alarm:%d   rest time:%d\r\n",sl,r_sl);

    if(sigwaitinfo(&set,&info)<0) perror("sigwaitinfo");
    else printf("pid:%d  vol:%d  sig:%s\r\n",info.si_pid,info.si_signo,strsignal(info.si_signo));

    sl++;
    if(sl>2) sl =1;
  }
}


// 精准定时器
// 其中的new_value参数用来对计时器进行设置，it_interval为计时间隔，it_value为延时时长，下面例子中表示的是在setitimer方法调用成功后，延时1微秒便触发一次SIGALRM信号，以后每隔200毫秒触发一次SIGALRM信号。
// settimer工作机制是，先对it_value倒计时，当it_value为零时触发信号，然后重置为it_interval，继续对it_value倒计时，一直这样循环下去。
// 基于此机制，setitimer既可以用来延时执行，也可定时执行。
// 假如it_value为0是不会触发信号的，所以要能触发信号，it_value得大于0；如果it_interval为零，只会延时，不会定时（也就是说只会触发一次信号)。
// old_value参数，通常用不上，设置为NULL，它是用来存储上一次setitimer调用时设置的new_value值。
#include <sys/time.h>
// int getitimer(int which, struct itimerval *curr_value);
// int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
/*
struct itimerspec {
	struct timespec it_interval;	/* timer period
	struct timespec it_value;	/* timer expiration 
};

struct itimerval {
	struct timeval it_interval;	/* timer interval
	struct timeval it_value;	/* current value
};
*/
static void Lap_setitimer()
{
  struct itimerval new_value,old_value;

    // 阻塞信号
  sigset_t set;
   (&set);
  sigaddset(&set,SIGALRM);
  sigprocmask(SIG_BLOCK,&set,NULL);

  // 自动重装载时间
  new_value.it_interval.tv_sec =0;
  new_value.it_interval.tv_usec =1000*500;

  // 定时时间
  new_value.it_value.tv_sec =0;
  new_value.it_value.tv_usec =1000*500;

  setitimer(ITIMER_REAL,&new_value,&old_value); // 周期发送SIG_ALARM
  while (1)
  {
    siginfo_t info;
    if(sigwaitinfo(&set,&info)<0) perror("sigwaitinfo");
    else printf("pid:%d sig:%s\r\n",info.si_pid,strsignal(info.si_signo));
  }
}


// 精准休眠nanosleep (sleep alarm setitimer 不可混用)
#include <time.h>
// int  nanosleep(const  struct  timespec *req, struct timespec* rem);
void handler(int sig)
{
  // printf("sig:%s\r\n",strsignal(sig));
  return;
}
static void Lap_nanosleep()
{
  // 阻塞信号
  struct sigaction act;
  sigemptyset(&act.sa_mask);
  sigaddset(&act.sa_mask,SIGINT);        // ctrr + z  暂停 fg:恢复到前台  bg:到后台
  act.sa_flags =0;
  act.sa_handler = handler;
  sigaction(SIGINT,&act,NULL);

  struct timespec req;
  struct timespec rem;
  req.tv_sec =10;
  req.tv_nsec =10000;
  int ret;
  while (1)
  {
    ret = nanosleep(&req,&rem);
    if(ret!= -1) exit(0); //定时时间到了

    printf("REST:%ld nanosleep 被信号中断\r\n",rem.tv_sec);
    req = rem;
  }
}


int main(void)
{
  //Lap_alarm();  // 定时
  // Lap_setitimer(); // 精准定时器
  Lap_nanosleep();    // 精准暂停系统一段时间
}
#endif